//
// Created by Symps on 2025/9/14.
//

#ifndef TEST25_6_14_BINARYTREE_H
#define TEST25_6_14_BINARYTREE_H

#include <iostream>
using namespace std;

template <typename T>
class BinaryTree {
public:
    class Node {
    public:
        T _value;
        Node* _left;
        Node* _right;

        explicit Node(T value) : _value(value), _left(nullptr), _right(nullptr) {}
        Node(T value, Node* left, Node* right) : _value(value), _left(left), _right(right) {}
        ~Node() {
        }
        Node& operator=(const Node& node) {
            if (this != &node) {
                delete _left;
                delete _right;

                _value = node._value;
                _left = node._left ? new Node(*node._left) : nullptr;
                _right = node._right ? new Node(*node._right) : nullptr;
            }
            return *this;
        }
    };

    BinaryTree(): _root(nullptr) {}

    void preOrder() const {
        cout << "[ ";
        preOrderInner(_root);
        cout << "]" << endl;
    }

    void inOrder() const {
        cout << "[ ";
        inOrderInner(_root);
        cout << "]" << endl;
    }

    void postOrder() const {
        cout << "[ ";
        postOrderInner(_root);
        cout << "]" << endl;
    }

    static void preOrder(Node* root) {
        cout << "[ ";
        preOrderInner(root);
        cout << "]" << endl;
    }

    static void inOrder(Node* root) {
        cout << "[ ";
        inOrderInner(root);
        cout << "]" << endl;
    }

    static void postOrder(Node* root) {
        cout << "[ ";
        postOrderInner(root);
        cout << "]" << endl;
    }


    ~BinaryTree() {
        destroyTree(_root);
    }

    void setRoot(Node* root) {
        destroyTree(_root);
        _root = root;
    }

    void setRoot(T value) {
        destroyTree(_root);
        _root = new Node(value);
    }

    Node* getRoot() const {
        return _root;
    }

    static Node* createNode(T value) {
        return new Node(value);
    }



private:
    Node* _root;

    static void destroyTree(Node* node) {
        if (node != nullptr) {
            destroyTree(node->_left);
            destroyTree(node->_right);
            delete node;
        }
    }

    static void preOrderInner(Node* root) {
        if (root == nullptr) {
            return;
        }
        cout << root->_value << " ";
        preOrderInner(root->_left);
        preOrderInner(root->_right);
    }

    static void inOrderInner(Node* root) {
        if (root == nullptr) {
            return;
        }
        inOrderInner(root->_left);
        cout << root->_value << " ";
        inOrderInner(root->_right);
    }

    static void postOrderInner(Node* root) {
        if (root == nullptr) {
            return;
        }
        postOrderInner(root->_left);
        postOrderInner(root->_right);
        cout << root->_value << " ";
    }
};


#endif //TEST25_6_14_BINARYTREE_H
